{% extends 'base.html' %}

{% block title %}Terms{% endblock %}
{% block header %}Terms{% endblock %}

{% block body %}

<p>
  <img id="showHideFilters" src="{{ url_for('static', filename='icn/plus-button.png') }}" />
  Filters
</p>
<div id="filterControls" style="display: none; margin-left: 20px;">
  <table>
    <tr>
      <td>Language</td>
      <td>
        <select id="filtLanguage">
          {% for langopt in language_options %}
          <option value={{ langopt[0] }}>{{ langopt[1] }}</option>
          {% endfor %}
        </select>
      </td>
    <tr>
      <td>Parent terms only</td>
      <td>
        <input id="filtParentsOnly" type="checkbox" />
      </td>
    </tr>
    <tr>
      <td>Age (days since created)</td>
      <td>
        <input id="filtAgeMin" style="width: 50px;" type="text" placeholder="min" />
        to
        <input id="filtAgeMax" style="width: 50px;" type="text" placeholder="max" />
      </td>
    </tr>
    <tr>
      <td>Status range</td>
      <td>
        <select id="filtStatusMin">
          <option value=0>(all)</option>
          <option value=1>New (1)</option>
          <option value=2>New (2)</option>
          <option value=3>Learn (3)</option>
          <option value=4>Learn (4)</option>
          <option value=5>Learned</option>
          <option value=99>Well Known</option>
        </select>
        to
        <select id="filtStatusMax">
          <option value=0>(all)</option>
          <option value=1>New (1)</option>
          <option value=2>New (2)</option>
          <option value=3>Learn (3)</option>
          <option value=4>Learn (4)</option>
          <option value=5>Learned</option>
          <option value=99>Well Known</option>
        </select>
      </td>
    </tr>
    <tr>
      <td>Include Ignored</td>
      <td>
        <input id="filtIncludeIgnored" type="checkbox" />
      </td>
    </tr>
  </table>
  <button id="clearFilters">Clear all</button>
  <br />
</div>


<div class="term-action-container">
  <div id="term_actions" class="term-action-dropdown" onmouseover="activate_term_actions();">
    <button class="term-action-button">Actions</button>
    <div class="term-action-content">
      <a href="/term/new">Create new</a>
      <a id="term_action_set_parent" href="#" onclick="show_hide_set_parent(event);">Set parent</a>
      <a id="term_action_bulk_delete" href="#" onclick="bulk_delete(event);">Delete selected</a>
      <a id="term_action_export_csv" href="#" onclick="export_csv(event);">Export CSV</a>
    </div>
  </div>

  <div id="set_parent_div" style="display: none;">
    <p>Set parent: <input id="txtSetParent" disabled /><button id="btnSetParent" disabled >go</button></p>
  </div>
</div>


<table id="termtable" class="table dataTable stripe">
  <thead>
    <tr>
      <th style="width: 20px;"><input type="checkbox" id="chkAll" onclick="handleChkAll()"></th>
      <!-- adding text-align because sometimes datatables seemed to align them to right. -->
      <th style="text-align: left">Term</th>
      <th style="text-align: left">Parent</th>
      <th style="text-align: left">Translation</th>
      <th style="text-align: left">Language</th>
      <th style="text-align: left">Tags</th>
      <th style="text-align: left">Status</th>
      <th style="text-align: left">Added</th>
      <th style="text-align: left">TermID</th>
      <th style="text-align: left">LanguageID</th>
    </tr>
  </thead>
</table>

<script>

  // Column indexes returned in the datatables json.
  const WORD_COL = 1;
  const TRANSLATION_COL = 3;
  const CREATED_DATE_COL = 7;
  const WID_COL = 8;
  const LID_COL = 9;
  const IMG_COL = 10;
  const STATUS_TEXT_COL = 13;

  let setup_term_datatable = function(initial_search) {
    var table = $('#termtable').DataTable({
      layout: {
        topStart: 'pageLength',
        topEnd: 'search',
        bottomStart: ['info', 'buttons'],
        bottomEnd: 'paging'
      },
      responsive: true,
      select: false,
      lengthMenu: [ 25, 50, 100, 500, 1000 ],

      // The button is included but the div.dt-buttons is hidden,
      // so that the button actions can be trigged by a link
      // in the "Actions" list.
      buttons: [
         {
           extend: 'download',
           url: '/term/export_terms',
           text: 'Export CSV',
         },
      ],
      paging: true,
      info: true,
      searching: true,
      processing: true,
      serverSide: true,
      stateSave: true,
      select: {
        style: 'multi',
        selector: 'td:first-child input[type="checkbox"]',
        className: 'row-selected'
      },
      search: { search: initial_search },
      columnDefs: [
        // "chk" is included in the underlying SQL query.
        // Without it, datatables would place the values
        // in the wrong table columns.  Ugly hack, but works.
        { name: "chk", targets: 0, searchable: false, orderable: false, data: null, render: render_checkbox },
        { name: "WoText", targets: WORD_COL, render: render_text },
        { name: "ParentText", targets: 2 },
        { name: "WoTranslation", targets: TRANSLATION_COL, width: "40%", searchable: true, render: render_translation },
        { name: "LgName", targets: 4 },
        { name: "TagList", targets: 5 },
        { name: "StID", targets: 6, render: render_status },
        { name: "WoCreated", targets: CREATED_DATE_COL, render: render_date_created },

        { name: "WoID", targets: WID_COL, visible: false },
        { name: "LgID", targets: LID_COL, visible: false },
        { name: "WiSource", targets: IMG_COL, visible: false },
        { name: "StAbbreviation", targets: 11, visible: false },
        { name: "SyncStatus", targets: 12, visible: false },
        { name: "StText", targets: STATUS_TEXT_COL, visible: false },
        { name: "WoRomanization", targets: 14, visible: false },
      ],

      // Ajax call
      ajax: {
        url: '/term/datatables',
        type: "POST",

        // Additional filters.  func calls are required to get the
        // current filter field values.  These are included in the
        // data sent to the controller, and are used by the
        // TermRepository.
        data: {
          filtLanguage: () => $('#filtLanguage').val(),
          filtParentsOnly: () => $('#filtParentsOnly').prop('checked'),
          filtAgeMin: () => $('#filtAgeMin').val(),
          filtAgeMax: () => $('#filtAgeMax').val(),
          filtStatusMin: () => $('#filtStatusMin').val(),
          filtStatusMax: () => $('#filtStatusMax').val(),
          filtIncludeIgnored: () => $('#filtIncludeIgnored').prop('checked')
        },

        dataType: "json"
      },

    });
  } // end setup_term_datatable


  let render_text = function ( data, type, row, meta ) {
    return `<a href="/term/edit/${row[WID_COL]}">${row[WORD_COL]}</a>`;
  };

  // Use the status ID for sorting, so Well Known comes after Learned (5),
  // but use the status text ("New (1)") for the cell display.
  let render_status = function ( data, type, row, meta ) {
    return row[STATUS_TEXT_COL];
  };

  let render_checkbox = function (data, type, row, meta) {
    return `<input type="checkbox" class="chkWord" name="wordids" wordid="${row[WID_COL]}" langid="${row[LID_COL]}" onclick="handleChkClick()">`;
  };

  let render_translation = function ( data, type, row, meta ) {
    let tx = row[TRANSLATION_COL] ?? '';
    tx = tx.replaceAll("\r\n", "<br />");
    let imgsrc = row[IMG_COL] ?? '';
    if (imgsrc != '')
      imgsrc = `<img class="term-listing-image" style="margin-top: 5px;" src="${imgsrc}" />`;
    let ret = [ tx, imgsrc ].filter((s) => s != '');
    return ret.join('<br />');
  };

  let render_date_created = function (data, type, row, meta) {
    const dt = row[CREATED_DATE_COL];
    const datepart = dt.split(' ')[0];
    return `<span title="${dt}">${datepart}</span>`;
  };


  let handleChkAll = function() {
    const v = $('#chkAll').prop('checked');
    $('.chkWord').each(function(i) {
      $(this).prop('checked', v);
    });
    handleChkClick(true);
  }

  let handleChkClick = function(leave_checkAll = false) {
    if (! leave_checkAll)
      $('#chkAll').prop('checked', false);
    const n = $('.chkWord:checked').length;
    const lang_id = get_lang_id();
    const disabled = ((n == 0) || lang_id == null);
    $("#txtSetParent").prop('disabled', disabled);
    $("#btnSetParent").prop('disabled', disabled);
  }


  /** Deactivate term Actions, activate if they're possible. */
  function activate_term_actions() {
    const disabled = "actionDisabled";
    const checked_count = $('.chkWord:checked').length;
    const lang_id = get_lang_id();

    let c = $("#term_action_bulk_delete");
    c.addClass(disabled);
    if (checked_count > 0)
      c.removeClass(disabled);

    c = $("#term_action_set_parent");
    c.addClass(disabled);
    if (checked_count > 0 && lang_id != null)
      c.removeClass(disabled);
  }


  function show_hide_set_parent(event) {
    event.preventDefault();
    if ($("#term_action_set_parent").hasClass("actionDisabled"))
      return;
    $("#set_parent_div").css("display", "flex");
    $("#txtSetParent").focus();
  }

  // Return the clicked checkboxes' language ID,
  // or null if the lang id isn't the same for all.
  let get_lang_id = function() {
    let langids = [];
    $('.chkWord:checked').each(function(i) {
      langids.push($(this).attr('langid'));
    });
    const unique_langids = [...new Set(langids)];
    if (unique_langids.length == 1) {
      return unique_langids[0];
    }
    return null;
  }

  let handle_set_parent_click = function() {
    const lang_id = get_lang_id();
    if (lang_id == null) {
      alert("All terms must be of the same language.");
      return;
    }
    let wordids = [];
    $('.chkWord:checked').each(function(i) {
      wordids.push($(this).attr('wordid'));
    });
    const ptxt = $('#txtSetParent').val();

    const resp = confirm(`Change parent for ${wordids.length} term(s) to "${ptxt}"?  Note this will *remove* any existing parents for these terms.`);
    if (! resp)
      return;

    data = {
      wordids: wordids,
      langid: lang_id,
      parenttext: ptxt
    };
    $.ajax({
      url: '/term/bulk_set_parent',
      method: 'POST',
      data: JSON.stringify(data),
      contentType: "application/json; charset=utf-8",
      success: function(data) {
        location.reload();
      }
    });
  }


  let set_up_parent_autocomplete = function() {
    $("#txtSetParent").autocomplete({
      source: function(request, response) {
        const lang_id = get_lang_id();
        if (lang_id == null) {
          // This should never occur; the text
          // box should be disabled if lang_id is null.
          response([], null);
        }

        const s = encodeURIComponent(request.term);
        $.ajax({
          url: `/term/search/${s}/${lang_id}`,
          type: 'GET',
          dataType: 'json',
          minLength: 2,
          success: function(data) {
            arr = data.map(function(word) {
              let label = word.text;
              if (word.translation != null && word.translation != '') {
                label = `${label} (${word.translation})`;
              }
              const obj = {
                label: label,
                value: word.text,
                word: word.text,
                translation: word.translation
              };
              return obj;
            });
            response(arr, data);
          }
        })
      }
    });
  };


  function bulk_delete(event) {
    event.preventDefault();
    if ($("#term_action_bulk_delete").hasClass("actionDisabled"))
      return;
    const checked = $('.chkWord:checked');
    const ids = checked.toArray().map(el => parseInt($(el).attr('wordid')));
    const t = (ids.length == 1) ? 'term' : 'terms';
    const resp = confirm(`Deleting ${ids.length} ${t}.  Continue?`);
    if (! resp)
      return;

    data = {
      wordids: ids
    };
    $.ajax({
      url: '/term/bulk_delete',
      method: 'POST',
      data: JSON.stringify(data),
      contentType: "application/json; charset=utf-8",
      success: function(data) {
        location.reload();
      }
    });
  }


  /** Click the export button.
   * I'm doing this so that the Datatables "export" extension button
   * works out of the box, but the actual call to export the CSV
   * is in the "Actions" list.
   */
  function export_csv(event) {
    event.preventDefault();
    /*
    // TODO export_csv: only export selected/checked terms?
    const checked = $('.chkWord:checked');
    const ids = checked.toArray().map(el => parseInt($(el).attr('wordid')));
    */
    const export_button = $('.dt-button:contains("Export CSV")');
    if (export_button.length === 0) {
      throw new Error("Export CSV button not found");
    }
    export_button.click();
  };


  let handle_filter_update = function() {
    const store = {
      filtLanguage: $('#filtLanguage').val(),
      filtDisplay: $('#filterControls').css('display'),
      filtParentsOnly: $('#filtParentsOnly').prop('checked'),
      filtAgeMin: $('#filtAgeMin').val(),
      filtAgeMax: $('#filtAgeMax').val(),
      filtStatusMin: $('#filtStatusMin').val(),
      filtStatusMax: $('#filtStatusMax').val(),
      filtIncludeIgnored: $('#filtIncludeIgnored').prop('checked')
    };
    // console.log('saving: ' + JSON.stringify(store));
    sessionStorage.setItem('termtable_filters', JSON.stringify(store));
    $('#termtable').DataTable().draw();
  };


  let load_filters_from_storage = function() {
    fs = sessionStorage.getItem('termtable_filters');
    // console.log(fs);
    if (fs == null)
      return;
    store = JSON.parse(fs);
    $('#filterControls').css('display', store.filtDisplay);

    if (store.filtDisplay == 'none')
      return;

    $('#showHideFilters').prop('src', "{{ url_for('static', filename='icn/minus-button.png') }}");
    $('#filtLanguage').val(parseInt(store.filtLanguage ?? '0'));
    $('#filtParentsOnly').prop('checked', store.filtParentsOnly ?? false);
    if ((store.filtAgeMin ?? '') != '')
      $('#filtAgeMin').val(parseInt(store.filtAgeMin));
    if ((store.filtAgeMax ?? '') != '')
    $('#filtAgeMax').val(parseInt(store.filtAgeMax));
    $('#filtStatusMin').val(parseInt(store.filtStatusMin));
    $('#filtStatusMax').val(parseInt(store.filtStatusMax));
    $('#filtIncludeIgnored').prop('checked', store.filtIncludeIgnored);

    // Have to re-load the data table, now that the filters have changed.
    $('#termtable').DataTable().draw();
  };
  
  let handle_show_hide_filter_click = function() {
    const fc = $('#filterControls');
    const is_hidden = (fc.css('display') == 'none');
    const new_src = is_hidden ? "{{ url_for('static', filename='icn/minus-button.png') }}" : "{{ url_for('static', filename='icn/plus-button.png') }}";
    $('#showHideFilters').prop('src', new_src);
    if (! is_hidden)
      handle_clear_filters();
    fc.css('display', is_hidden ? 'block' : 'none');
    handle_filter_update();
  };

  let handle_clear_filters = function() {
    $('#filtLanguage').val(0);
    $('#filtParentsOnly').prop('checked', false);
    $('#filtAgeMin').val('');
    $('#filtAgeMax').val('');
    $('#filtStatusMin').val(0);
    $('#filtStatusMax').val(0);
    $('#filtIncludeIgnored').prop('checked', false);
    handle_filter_update();
  };

  $(document).ready(function () {
    setup_term_datatable("{{ initial_search or '' }}");
    set_up_parent_autocomplete();
    $('#btnSetParent').click(handle_set_parent_click);
    $('#showHideFilters').click(handle_show_hide_filter_click);

    $('#filtLanguage').change(handle_filter_update);
    $('#filtParentsOnly').change(handle_filter_update);
    $('#filtAgeMin').keyup(handle_filter_update);
    $('#filtAgeMax').keyup(handle_filter_update);
    $('#filtStatusMin').change(handle_filter_update);
    $('#filtStatusMax').change(handle_filter_update);
    $('#filtIncludeIgnored').change(handle_filter_update);
    $('#clearFilters').click(handle_clear_filters);

    load_filters_from_storage();
  });


</script>

{% endblock %}
